﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace NullTodoList
{
    /// <summary>
    /// Класс реализующий таблицу с активной ячейкой.
    /// </summary>
    public partial class CustomGrid : TableLayoutPanel
    {
        private Point activeCell;

        /// <summary>
        /// Конструктор по-умолчанию.
        /// </summary>
        public CustomGrid()
        {
            InitializeComponent();
            DoubleBuffered = true;
        }

        private Int32 GetIntervalIndex(Int32[] intervals, Int32 value)
        {
            var begin = 0;
            var end = 0;
            for (var i = 0; i < intervals.Length; i++)
            {
                end += intervals[i];
                if (value >= begin && value < end)
                    return i;
                begin = end;
            }
            return -1;
        }

        /// <summary>
        /// Вызов события-уведомления о начале изменения активной ячейки.
        /// </summary>
        /// <param name="e">Параметр, содержащий координаты ячейки, которая должна стать активной.</param>
        protected virtual void OnActiveCellChanging(ActiveCellChangingEventArgs e)
        {
            if (ActiveCellChanging != null)
                ActiveCellChanging(this, e);
        }

        /// <summary>
        /// Вызов события-уведомления об изменении активной ячейки.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnActiveCellChanged(EventArgs e)
        {
            if (ActiveCellChanged != null)
                ActiveCellChanged(this, e);
        }

        /// <summary>
        /// Клик мышкой и установление новой активной ячейки.
        /// </summary>
        /// <param name="e">Параметр, содержащий дополнительные значения.</param>
        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            ActiveCell = new Point(
                GetIntervalIndex(GetColumnWidths(), e.X),
                GetIntervalIndex(GetRowHeights(), e.Y)
            );
        }

        /// <summary>
        /// Координаты активной ячейки.
        /// </summary>
        public Point ActiveCell
        {
            get { return activeCell; }
            set
            {
                if (activeCell == value)
                    return;
                var args = new ActiveCellChangingEventArgs(value, false);
                OnActiveCellChanging(args);
                if (!args.Cancel)
                {
                    activeCell = value;
                    OnActiveCellChanged(EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Событие-уведомление о начале изменения активной ячейки.
        /// </summary>
        public event EventHandler<ActiveCellChangingEventArgs> ActiveCellChanging;
        /// <summary>
        /// Событие-уведомление об изменении активной ячейки.
        /// </summary>
        public event EventHandler ActiveCellChanged;
    }

    /// <summary>
    /// Аргумент для события изменения активной ячейки.
    /// </summary>
    public class ActiveCellChangingEventArgs : CancelEventArgs
    {
        /// <summary>
        /// Конструктор по-умолчанию.
        /// </summary>
        public ActiveCellChangingEventArgs()
            : base()
        {
        }

        /// <summary>
        /// Конструктор с параметрами.
        /// </summary>
        /// <param name="cell">Координаты ячейки.</param>
        /// <param name="cancel">Флаг разрешения изменения.</param>
        public ActiveCellChangingEventArgs(Point cell, Boolean cancel = false)
            : base(cancel)
        {
            Cell = cell;
        }

        /// <summary>
        /// Координаты ячейки, которая должна стать активной.
        /// </summary>
        public Point Cell
        {
            get;
            set;
        }
    }
}
